#ifndef _NODE_H
#define _NODE_H

#include <memory>
#include <tr1/memory>
#include <cassert>

/*
 * ValueType needs to implement >, <, == operator
*/
template<class KeyType, class ValueType>
class Node
{
public:
	Node(std::pair<KeyType, ValueType> keyValuePair, unsigned height) : 
		mKeyValuePair(keyValuePair), 
		mHeight(height)
	{
		mNext = new std::tr1::shared_ptr<Node<KeyType, ValueType> >[mHeight];
	}

	Node(KeyType key, ValueType value, unsigned height) : 
		mKeyValuePair(key,value),
		mHeight(height)
	{ 
		
	}

	Node(const Node<KeyType, ValueType>& o)
	{
		this->mKeyValuePair = o.mKeyValuePair;
		this->mNext = o.mNext;
		this->mHeight = o.mHeight;
	}
		
	~Node() 
	{
		delete [] mNext;
	}
    
    Node<KeyType, ValueType> *getNextNode(unsigned height)
    {
        assert(height >= mHeight);
        return mNext[height];
    }
    
	Node& operator= (const Node<KeyType, ValueType>& other)
	{
		if(this != other)
		{
			// 1: allocate new memory and copy the elements
			std::tr1::shared_ptr<Node>* new_array = new std::tr1::shared_ptr<Node>[other.mHeight];
            
			std::copy(other.mNext, other.mNext + other.mHeight, new_array);
 
            // 2: deallocate old memory
            delete [] mNext;
 
            // 3: assign the new memory to the object
			mNext = new_array;
			mHeight= other.mHeight;
		}
		return *this;
	}
    
	bool operator> (const Node<KeyType, ValueType>& other)
	{
		return (this->mKeyValuePair.second > other.mKeyValuePair.second);
	}

	bool operator< (const Node<KeyType, ValueType>& other)
	{		
		return (this->mKeyValuePair.second < other.mKeyValuePair.second);
	}

	bool operator== (const Node<KeyType, ValueType>& other)
	{		
		return (this->mKeyValuePair.second == other.mKeyValuePair.second);
	}

	std::pair<KeyType, ValueType> mKeyValuePair;
	std::tr1::shared_ptr<Node<KeyType, ValueType> > *mNext;
	unsigned mHeight;
};
#endif /*_NODE_H */ 
